library Multibars initializer InitMultibars
/*
Multibars Readme (vJass)

Created by Ammorth

Compiled January 10th, 2008

Requires vJass


PLEASE GIVE CREDIT IF YOU USE MULTIBARS OR ANY OF MY BARTYPES IN YOUR MAP!

==================================
About
==================================

Multibars is an easy way to create dynamic and sexy looking progress bars for multiboards.
You can also create dynamic health, mana and experience bars with 1 line of code.
Included in this version are 11 different bartypes:

Name        - Type                  (Description)

Build       - MULTIBAR_TYPE_BUILD        (based on the in-game construction bar)
Health      - MULTIBAR_TYPE_HEALTH       (A red health bar)
Mana        - MULTIBAR_TYPE_MANA         (A blue mana bar)
Experience  - MULTIBAR_TYPE_EXPERIENCE   (A purple experience bar)
Chunk       - MULTIBAR_TYPE_CHUNK        (A green bar that displays in chunks, rather than smoothly)
Radio       - MULTIBAR_TYPE_RADIO        (A radioactive [yellow and black] bar)
Mac         - MULTIBAR_TYPE_MAC          (resembles a Mac OS X loading bar)
Orange      - MULTIBAR_TYPE_ORANGE       (An orange bar that displays in chuncks, but chunks light up vs. appearing)
Hearts      - MULTIBAR_TYPE_HEARTS       (Hearts which display health based off of Zelda Ocarina of Time)
Hearts Up   - MULTIBAR_TYPE_HEARTS_UP    (Hearts with a white outline which display health, based off of Zelda Ocarina of Time)
Magic       - MULTIBAR_TYPE_MAGIC        (Green energy bar based off of Zelda Ocarina of Time)


==================================
Installation
==================================

1) Copy the Multibars Library to your map (copy the trigger and paste it)
2) For each type of bar you want to use, import the entire folder to your map
3a) If you want to use the dynamic health, mana and experience bars, copy the MutliBarsHelper library aswell
3b) Change the MULTIBAR_PERIOD constant if you want the bars updating smoother or mre efficiently.


==================================
Usage
==================================

To create a Multibar, call:

static method create takes multiboard whichboard, integer colstart, integer row, integer size, real maxval, real currentval, integer bartype returns MultiBar
- whichboard - the multiboard which the bar will be added to
//要添加进度条的多面板
- colstart - which column do you want the bar to start on
//始列
- row - which row do you want the bar on
//位于行
- size - how many columns do you want to use for your bar (max of 16, min of 2)
//将多少列用于进度条(最大16,最小2)
- maxval - the maximum value of the bar
//进度条的最大值
- currentval - the starting value the bar will display
//开始值
- bartype - the bartype of the bar (Defualts are shown in the table above)
//进度条的风格
An example of calling this function would be:

local Multibar mb = Multibar.create(SomeMultiboard, 3, 0, 12, 50., 10., BAR_TYPE_BUILD)
- This would create a Build Multibar on SomeMultiboard, at column 4, row 1, (remember, multiboards in jass start at 0,0) a size of 12,
  max value is 50, and the current value is 10.



To update the value of the bar, call:

method UpdateValue takes real newvalue, boolean update returns nothing
- newvalue - the new current value
//新的进度值
- update - if you want the bar to visually update to the new value
//是否更新进度条
An exmaple of calling this function would be:

call mb.UpdateValue(45., true)
- This would update our Multibar stored in mb to a value of 45.  It would also update the visual bar on the multiboard.


To update the maximum value of the bar, call:

method UpdateMaxValue takes real newvalue, boolean update returns nothing
- newvalue - the new maximum value
//新的最大进度值
- update - if you want the bar to visually update to the new value
//是否更新进度条
An exmaple of calling this function would be:

call mb.UpdateValue(45., true)
- This would update our Multibar stored in mb to a value of 45.  It would also update the visual bar on the multiboard.
- Note: if the maximum value becomes less than the current value, the current value will automatically equal the new max value.
//如果当前值大于最大进度值,则系统会自动将当前值设为最大进度值


//###########################################################################

To create dynamic Health, Mana or Experience bars, make sure you have the MultibarsHelper library installed then call:

static method create takes unit whichunit, multiboard whichboard, integer col, integer row, integer size, integer bartype, integer whichtype returns MultiBarHelper
- whichunit - the unit you want to create the bar for
//要创建单位属性进度条的单位
- whichboard - the multiboard which the bar will be added to
//要添加进度条的多面板
- col - which column do you want the bar to start on
//始列
- row - which row do you want the bar on
//位于行
- size - how many columns do you want to use for your bar (max of 16, min of 2)
//将多少列用于进度条(最大16,最小2)
- bartype - the bartype of the bar (Defualts are shown in the table above)
//进度条的风格
- whichtype - the type of the helper bar.
//辅助进度条风格
            - MULTIBAR_HELPER_HEALTH = health bar
            - MULTIBAR_HELPER_MANA = mana bar
            - MULTIBAR_HELPER_EXPERIENCE = experience bar

This function will create a helper bar that will automatically update itself, depending on the units status.

An exmaple of calling this functions is:

local MultibarHelper h = MultibarHelper.create(someunit, someboard, 0, 0, 14, MULTIBAR_TYPE_HEALTH, MULTIBAR_HELPER_HEALTH)
- This function would create a health bar at col 0 row 0 on someboard, displaying the health of someunit.
- The types used do not have to be the default types.  For example, you can use MULTIBAR_TYPE_CHUNK for a health bar.


If you want to create a label for your health, mana, or experience bar, call:

method AddLabel takes integer col, integer row, real width, integer red, integer green, integer blue, integer alpha, string icon returns nothing
- col - which column you want the label to be on
//标签位于列
- row - which row you want the label to be on
//标签位于行
- width - the width you want the label cell to be
//标签单元格宽度
- red/green/blue/alpha - the color your want the label to be
//标签颜色RGBA
- icon - the icon you want beside the label (use "" for no icon)
//标签旁边的图标(使用""不显示图标)
Labels can only be created for MultiBarHelpers bars (health, mana, experience).  Attempting to create a label for a regular MultiBar bar will
produce an error.
//标签只能用于辅助进度条(如生命,魔法,经验),用于常规进度条会出错.
An exmaple of calling this function would be:

call somebarhelper.AddLabel(0, 2, 0.07, 0, 0, 255, 255, "")
- This will create a label for somebar at column 0, row 2, with a width of 7%, blue text and no icon.
- Labels are automatically cleared from memory when the multibarhelper is destroyed.
- You can only have 1 label per multibarhelper.


When you are done with a MultiBar, dont forget to call:

method destroy takes nothing returns nothing
//进度条的销毁.
An example of calling this function would be:

call mb.destroy()
- This will remove the Multibar or MultibarHelper from memory, but will not remove the visuals from the multiboard.  To do this, either clear the multiboard or replace it with something else.
- Always remember to destroy multibars and multibarhelpers when you are done with them.
*/

globals
    // ====================
    // PUBLIC CONSTANTS
    // ====================

    // These constants should not be modified

    constant integer MULTIBAR_TYPE_HEALTH = 1
    constant integer MULTIBAR_TYPE_MANA = 2
    constant integer MULTIBAR_TYPE_EXPERIENCE = 3
    constant integer MULTIBAR_TYPE_BUILD = 4
    constant integer MULTIBAR_TYPE_CHUNK = 5
    constant integer MULTIBAR_TYPE_RADIO = 6
    constant integer MULTIBAR_TYPE_MAC = 7
    constant integer MULTIBAR_TYPE_ORANGE = 8
    constant integer MULTIBAR_TYPE_HEARTS = 9
    constant integer MULTIBAR_TYPE_HEARTS_UP = 10
    constant integer MULTIBAR_TYPE_MAGIC = 11


    // ====================
    // END PUBLIC CONSTANTS
    // ====================


    //Private Variables

    private integer Gcurrent = 0
    private string array Gbartype
    private string array Gfiletype
    private string array Gdir
    private integer array Gdivs

endglobals

struct Multibar
    integer row
    integer colstart
    integer numcols
    integer numdivs
    real max
    real current
    string bartype
    string filetype
    string dir
    multiboard whichboard
    integer array curfill[16]

    private method UpdateBoard takes nothing returns nothing
        local real step = .max/.numcols
        local real step2 = step/.numdivs
        local real val = .current
        local multiboarditem mbi
        local integer col = .colstart
        local integer num
        loop
            exitwhen val <= 0.
            if val >= step then
                if .curfill[col] != .numdivs then // check if it requires an update
                    set mbi = MultiboardGetItem(.whichboard, .row, col)
                    if col == .colstart then
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"L"+I2S(.numdivs)+.filetype) // Left
                    elseif col == .colstart+.numcols-1 then
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"R"+I2S(.numdivs)+.filetype) // Right
                    else
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"M"+I2S(.numdivs)+.filetype) // Middle
                    endif
                    call MultiboardReleaseItem(mbi)
                    set .curfill[col] = .numdivs
                endif
                set val = val - step
            else
                set num = R2I((val/step2)+0.5)
                if .curfill[col] != num then // check if it requires an update
                    set mbi = MultiboardGetItem(.whichboard, .row, col)
                    if col == .colstart then
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"L"+I2S(num)+.filetype) // Left
                    elseif col == .colstart+.numcols-1 then
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"R"+I2S(num)+.filetype) // Right
                    else
                        call MultiboardSetItemIcon(mbi, .dir+.bartype+"M"+I2S(num)+.filetype) // Middle
                    endif
                    call MultiboardReleaseItem(mbi)
                    set .curfill[col] = num
                endif
                set val = 0.
            endif
            set col = col + 1
        endloop
        loop
            exitwhen col >= .colstart + .numcols
            if .curfill[col] != 0 then // check if it requires an update
                set mbi = MultiboardGetItem(.whichboard, .row, col)
                if col == .colstart then
                    call MultiboardSetItemIcon(mbi, .dir+.bartype+"L0"+.filetype) // Left
                elseif col == .colstart+.numcols-1 then
                    call MultiboardSetItemIcon(mbi, .dir+.bartype+"R0"+.filetype) // Right
                else
                    call MultiboardSetItemIcon(mbi, .dir+.bartype+"M0"+.filetype) // Middle
                endif
                call MultiboardReleaseItem(mbi)
                set .curfill[col] = 0
            endif
            set col = col + 1
        endloop
        set mbi = null
    endmethod

    private method SetMultiboardBar takes nothing returns nothing
        local integer col = .colstart
        local integer end = col + .numcols
        local multiboarditem mbi
        loop
            exitwhen col >= end
            set mbi = MultiboardGetItem(.whichboard, .row, col)
            call MultiboardSetItemWidth(mbi, 0.01)
            call MultiboardSetItemStyle(mbi, false, true)
            call MultiboardReleaseItem(mbi)
            set col = col + 1
        endloop
        set mbi = null
    endmethod

    static method create takes multiboard whichboard, integer colstart, integer row, integer size, real maxval, real currentval, integer bartype returns Multibar
        local Multibar b = Multibar.allocate()
        local integer i = 0
        set b.whichboard = whichboard
        if row > 32 then
            debug call BJDebugMsg("Multibars Error: Multiboards only have 32 rows!")
        elseif row < 0 then
            debug call BJDebugMsg("Multibars Error: Multiboards do not have negative rows!")
        endif
        set b.row = row
        set b. colstart = colstart
        if colstart > 16 then
            debug call BJDebugMsg("Multibars Error: Multiboards only have 16 columns")
        elseif colstart < 0 then
            debug call BJDebugMsg("Multibars Error: Multiboards do not have negative columns!")
        endif
        if size < 2 then
            debug call BJDebugMsg("Multibars Error: Bar size must be greater than 1!")
        elseif size > 16 then
            debug call BJDebugMsg("Multibars Error: Bar size must be less than 17!")
        endif
        set b.numcols = size
        set b.max = maxval
        if maxval < 0 then
            debug call BJDebugMsg("Multibars Error: Multibars does not support negative values!")
            set b.max = 1
        endif
        set b.current = currentval
        if currentval < 0 then
            debug call BJDebugMsg("Multibars Error: Multibars does not support negative values!")
            set b.current = 0
        elseif currentval > b.max then
            debug call BJDebugMsg("Multibars Error: Value cannot exceed max value!")
            set b.current = b.max
        endif
        if bartype > Gcurrent then
            debug call BJDebugMsg("Multibars Error: Invalid bartype!")
        endif
        set b.numdivs = Gdivs[bartype]
        set b.bartype = Gbartype[bartype]
        set b.filetype = Gfiletype[bartype]
        set b.dir = Gdir[bartype]
        loop
            exitwhen i > 15
            set b.curfill[i] = -1
            set i = i + 1
        endloop
        call b.SetMultiboardBar()
        call b.UpdateBoard()
        return b
    endmethod

    method destroy takes nothing returns nothing
        set .whichboard = null
        call this.deallocate()
    endmethod

    method UpdateValue takes real newvalue, boolean update returns nothing
        if newvalue > .max then
            set .current = .max
        elseif newvalue < 0. then
            set .current = 0.
        else
            set .current = newvalue
        endif
        if update then
            call .UpdateBoard()
        endif
    endmethod

    method UpdateMaxValue takes real newvalue, boolean update returns nothing
        if newvalue < 1 then
            set .max = 1
        else
            set .max = newvalue
        endif
        if .current > .max then
                set .current = .max
            endif
        if update then
            call .UpdateBoard()
        endif
    endmethod

endstruct

public function CreateBartype takes string name, string filetype, string directory, integer divisions returns integer
    set Gcurrent = Gcurrent + 1
    set Gbartype[Gcurrent] = name
    set Gfiletype[Gcurrent] = filetype
    set Gdir[Gcurrent] = directory
    set Gdivs[Gcurrent] = divisions
    return Gcurrent
endfunction

private function CreateNativeBartype takes integer bartype, string name, string filetype, string directory, integer divisions returns nothing
    if bartype > Gcurrent then
        set Gcurrent = bartype
    endif
    set Gbartype[bartype] = name
    set Gfiletype[bartype] = filetype
    set Gdir[bartype] = directory
    set Gdivs[bartype] = divisions
endfunction

private function InitMultibars takes nothing returns nothing
    // Set-up Native Bartypes
    call CreateNativeBartype(MULTIBAR_TYPE_HEALTH, "Health", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_MANA, "Mana", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_EXPERIENCE, "Experience", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_BUILD, "Build", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_CHUNK, "Chunk", ".tga", "Multibars\\", 2)
    call CreateNativeBartype(MULTIBAR_TYPE_RADIO, "Radio", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_MAC, "Mac", ".tga", "Multibars\\", 8)
    call CreateNativeBartype(MULTIBAR_TYPE_ORANGE, "Orange", ".tga", "Multibars\\", 2)
    call CreateNativeBartype(MULTIBAR_TYPE_HEARTS, "ZeldaHearts", ".tga", "Multibars\\", 4)
    call CreateNativeBartype(MULTIBAR_TYPE_HEARTS_UP, "ZeldaHeartsUp", ".tga", "Multibars\\", 4)
    call CreateNativeBartype(MULTIBAR_TYPE_MAGIC, "ZeldaMagic", ".tga", "Multibars\\", 8)
endfunction

endlibrary
